--[[
 this is a lua module which implementing the 
 oled screen driver interface on the nodemcu platform   
 autor: zhangoneone
 Nov. 2022 
--]]

gui_mgr = {}

gui_mgr.id  = 0
gui_mgr.sda = 5 -- GPIO14
gui_mgr.scl = 6 -- GPIO12
gui_mgr.sla = 0x3c
-- display object
local disp
local update_co

local function i2c_setup(sda, scl)
    gui_mgr.sda = sda
    gui_mgr.scl = scl
    node.setcpufreq(node.CPU160MHZ)
    i2c.setup(gui_mgr.id, gui_mgr.sda, gui_mgr.scl, i2c.FASTPLUS) --1MHZ
    disp = u8g2.ssd1306_i2c_128x64_noname(gui_mgr.id, gui_mgr.sla)

end

local function u8g2_prepare()
  disp:setFont(u8g2.font_unifont_t_chinese3)
  --disp:setFont(u8g2.font_6x10_tr)
  disp:setFontRefHeightExtendedText()
  disp:setDrawColor(1)
  disp:setFontPosTop()
  disp:setFontDirection(0)
end

--default logo
local function def_logo()
  disp:drawUTF8(0,10, "welcome to venus")
  disp:drawUTF8(10,35, "Nov,2022,one")
end

-- ui fresh co, after user invoke the desire_update, this will fresh the UI
local function fresh_daemon(draw)
    while true do
        if draw == nil then
            draw = def_logo()
        end
        disp:clearBuffer()
        --注意这里即使是死循环,如果draw函数运行出错，也会把当前协程结束掉
        --如果此时继续resume该协程，就会出错，因此其他地方resume时,应该首先检查协程状态
        --处于dead状态的，不应该被resume
        --考虑当前的例子,还需要把协程重新恢复，才是最好的
        draw()
        disp:sendBuffer()
        -- fresh done, send feedback to resume, then give up cpu
        draw = coroutine.yield()
    end
end

function gui_mgr.desire_update(draw)
    -- resume co，make the fresh daemon work continuous
    local status, val = coroutine.resume(update_co, draw)
    if status == false then
        print("resume the co fail "..val.."\n")
    end
    return status
end

function gui_mgr.gui_init(sda, scl)
    i2c_setup(sda,scl)
    u8g2_prepare()
    update_co = coroutine.create(fresh_daemon)
    --invoke the co first, show the default logo
    local status, val = coroutine.resume(update_co, def_logo)
    if status == false then
        print("start co fail\n")
    end
    return status
end

function gui_mgr.get_disp()
    return disp
end
function gui_mgr.exit()
    node.setcpufreq(node.CPU80MHZ)
end

return gui_mgr
